"ui";
ui.statusBarColor("#099256");
const set = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/";
var storage = storages.create("qq7513241");
var filev = "/sdcard/脚本" //默认脚本目录；
importClass(android.app.AlertDialog);
importClass(android.content.Intent);
importClass(android.net.Uri);
importClass(java.io.File);
/**
 * 论坛网址：https://www.learnyun.net/
 * 交流 Q群：4607221
 * 
 * 用途：方便对整个脚本文件加密
 * 用法：加密后的脚本可以放到任何地方加载， 本地放一个解密函数即可，只需要把解密函数单独做dex或者转so文件。
 * 转发请保留此说明，谢谢！
 */

/**--------------------以下是解密函数*/
/**
 * @param {*} sKey  传入你的加密秘钥
 * @param {*} sSrc   传入加密的密文
 */
const aesDecrypt = function (sKey, sSrc) {
    var src = android.util.Base64.decode(sSrc, 2)
    var iv = new javax.crypto.spec.IvParameterSpec(new java.lang.String(sKey).getBytes());
    var keyb = new java.lang.String(sKey).getBytes();
    var raw = java.security.MessageDigest.getInstance("MD5").digest(keyb);
    var skeySpec = new javax.crypto.spec.SecretKeySpec(raw, "AES");
    var cipher = javax.crypto.Cipher.getInstance("AES/CBC/PKCS5Padding");
    cipher.init(javax.crypto.Cipher.DECRYPT_MODE, skeySpec, iv);
    var encryptedData = cipher.doFinal(src);
    return new java.lang.String(encryptedData, "UTF-8");
}
/**--------------------以上是解密函数 */

let d = function (n) {
    let d = [0x6e, 0xa, 0x1, 0x1, 0x1, 0xb, 0xa, 0xa, 0x1, 0x1, 0xa, 0x1, 0xb, 0xb, 0x1, 0x1, 0x1, 0x1, 0x1, 0x1, 0xb, 0xb, 0xb, 0xb, 0xb, 0xb]
    for (let i = 0; i < d.length; i++) for (let indx = 0; indx < parseInt(d[i], 2); indx++)  (i + 1) % 2 === 0 ? n = n + 0x0.toString() + set[random(0, set.length - 20)] : (i + 1) % 2 !== 0 ? n = n + 0x1.toString() + set[random(0, set.length - 20)] : false;
    return n
}()

ui.layout(
    <vertical bg="#efefef">
        <appbar h="auto" bg="#099256" >
            <frame h="auto" marginTop="20px">
                <vertical w="*" h="*">
                    <horizontal gravity="center_vertical" padding="0 15"  >
                        <img w="50" tint="#b9dbc4" padding="10 0 10 0" margin="0 0 5 0" clickable="true" bg="?attr/selectableItemBackground" src="@drawable/ic_apps_black_48dp" />
                        <frame layout_weight="1">
                            <text id="title" textColor="#ffffff" textStyle="bold" margin="-20 0 0 0" textSize="19" text="{{setMetdx('sDoDrnutKggJJPPZtbQjLqCcgiLjq2+T53ATcLiWDoI=')}}" gravity="center" />
                        </frame>
                        <img w="45" tint="#ffffff" id="shareScript" margin="0 0 5 0" padding="10 0 10 0" clickable="true" bg="?attr/selectableItemBackground" src="@drawable/ic_share_black_48dp" />
                    </horizontal >
                </vertical>
            </frame>
        </appbar>
        <horizontal gravity="center_vertical" margin="5 0 5 5">
            <card id="indx1" layout_weight="1" margin="5 5 1 5" h="40" cardCornerRadius="3"
                cardElevation="1dp" gravity="center_vertical"  >
                <horizontal layout_weight="1" gravity="center_vertical"  >
                    <text w="auto" h="auto" textSize="14" margin="8 0 0 0" textColor="#222222" text="{{setMetdx('JNL7mHZshpg172j2kaEEFQ==')}}" />
                    <text layout_gravity="center" layout_weight="1" margin="5 0 5 0 " w="*" padding="0" textColor="#9a9a9a" background="#00000000" id="routeFile" maxLines="1" textSize="14sp" hint="{{setMetdx('Xbv2oOtcXLuGCRyqEAZSW4AujPjo8EDBPY0y2JXwanU=')}}" />

                </horizontal>
            </card>
            <card id="indx1" w="90" margin="0 5 5 5" h="40" cardCornerRadius="3"
                cardElevation="2dp" gravity="center_vertical" cardBackgroundColor="#f6f3f3">
                <text layout_weight="1" h="*" gravity="center" textSize="14" clickable="true" id="selectFile" bg="?attr/selectableItemBackground" textColor="#099256" text="{{setMetdx('fOhqmPQUenU1cYvGfBpvXw==')}}" />
            </card>
        </horizontal>

        <horizontal gravity="center_vertical" margin="5 0 5 5">
            <card id="indx1" layout_weight="1" margin="5 5 1 5" h="40" cardCornerRadius="3"
                cardElevation="1dp" gravity="center_vertical"  >
                <horizontal layout_weight="1" gravity="center_vertical"  >
                    <text w="auto" h="auto" textSize="14" margin="8 0 0 0" textColor="#222222" text="{{setMetdx('F74iHfk0gJbgt0FyB27ZJA==')}}" />
                    <input layout_gravity="center" layout_weight="1" margin="5 0 5 0 " w="*" padding="0" textColor="#099256" background="#00000000" id="password" maxLines="1" textSize="14sp" hint="{{setMetdx('EfMAuDsCnr5UnOeKGh6ANMe8mt+BSXvIdmO9QSO57/8=')}}" />

                </horizontal>
            </card>
            <card id="indx1" w="90" margin="0 5 5 5" h="40" cardCornerRadius="3"
                cardElevation="2dp" gravity="center_vertical" cardBackgroundColor="#f6f3f3">
                <spinner layout_weight="1" h="auto" textSize="13" margin="0 0 0 0" textColor="#099256" id="choice" entries="{{setMetdx('4LpwEAuuE4ga8S20HvukSg==')}}" spinnerMode="dialog" />
            </card>
        </horizontal>

        <card w="*" id="indx5" margin="8 0 8 10" h="45" cardCornerRadius="18"
            cardBackgroundColor="#099256" cardElevation="1dp" >
            <text id="运行程序" clickable="true" bg="?attr/selectableItemBackground" text="运行程序" textColor="#ffffff" textSize="20" gravity="center" />
        </card>
        <card id="indx6" w="*" margin="8 0 8 10" h="*" cardCornerRadius="6"
            cardElevation="3dp"  >
            <card w="*" h="*" cardCornerRadius="6" cardElevation="3dp"  >
                <vertical w="*" h="*" >
                    <horizontal h="30" gravity="center" >
                        <text margin="10 0 0 0" layout_weight="1" text="{{setMetdx('s8O/PH0PoCAzYqbWs8AjhooOzK4SRh4Y6KiWbo8+sU4+qld64MsazTQQCH8cFGVq')}}" textColor="#999999" textSize="14" />
                        <text margin="0 0 10 0" clickable="true" id="clear" gravity="right" bg="?attr/selectableItemBackground" text="{{setMetdx('jXXKAFIux4S8X3RyXbG+0g==')}}" textColor="#0675b5" textSize="14" />
                    </horizontal>
                    <View w="*" h="2px" bg="#f5f2f2" />
                    <ScrollView h="*" fadeScrollbars="false" Margin="0" layout_width="fill_parent" scrollbarStyle="outsideOverlay" background="@android:drawable/edit_text" >
                        <frame>
                            <text id="codeScript" margin="5 2 5 2" text="" textColor="#000000" textSize="14" />
                        </frame>
                    </ScrollView>
                </vertical>
            </card>
        </card>
    </vertical>
);
ui["codeScript"]["setHint"](setMetdx('kLujHvGrqCN/tJTobwONLcMMO1Qt5oK+bL0FXcy7KoB9dAoD0AmX2EQPggZu5Yhw'));
ui.clear.click(() => ui.codeScript.text("") || ui.routeFile.text(""))
ui.selectFile.on("click", function () {
    build({
        title: setMetdx('Sb4CPzZ0kO6KMrNJkACOm3ppnkM44H4Cs1tr3KbN9h4='),
        dir: eval(set[31] + set[34] + set[37] + set[30] + set[47]),
        canChoose: ["file"],
        fileCallback: (file) => {
            ui.run(function () {
                ui.routeFile.text(file)
            })
            let t = open(file).read();
            if (t) ui.run(function () {
                ui.codeScript.text(t)
            })
        }
    }).show();
})

ui.shareScript.on("click", function () {
    if (!ui.routeFile.text()) return toast(setMetdx('zDGrZj77pHjJ2X6xj8vGSaN7gSFYcjrYvvM97LgTWcgLy2V6RJthaPtFKwW58TQd'));
    new FileChooser().share(context, new Uri.parse(ui.routeFile.text()))
});
ui.run(() => ui.password.text(storage.get("password") || ""))
ui.运行程序.on("click", function () {
    let routeFile = ui.routeFile.text();
    let codeScript = ui.codeScript.text();
    let parssword = ui.password.text();
    if (!routeFile) return toast(setMetdx('Sb4CPzZ0kO6KMrNJkACOmyOYLaHfHo+HEy7fTm2W/0A='));
    if (!codeScript) return toast(setMetdx('XAr/5XvCFpTnERbXmo8FRoZ0i16rc7zx9epwL0Z5rjY='));
    if (!parssword) return toast(setMetdx('KoSG3m9kAszbOXOA6x7bbhYaVg12UENNqyLx7Mhfc0E='));
    if (parssword.length != 16) return toast(setMetdx('EfMAuDsCnr5UnOeKGh6ANMe8mt+BSXvIdmO9QSO57/8='));
    storage.put("password", ui.password.text());
    let type = ui.choice.getSelectedItemPosition();
    new FileChooser().mianThread(routeFile, codeScript, parssword, type)
})
function getParentDir(dir) {
    return new java.io.File(dir).parent;
}
function FileChooser(options) {
    // 当前文件列表数据
    this.data = [];
    // 当前被选中的位置
    this.selectedPos = -1;
    this.options = options;
    this.view = this.renderView();
    this.share = function (ctx, uri) {
        sendIntent = new Intent();
        sendIntent.setAction(Intent.ACTION_SEND);
        sendIntent.putExtra(Intent.EXTRA_STREAM, uri);
        sendIntent.setType("*/*");
        ctx.startActivity(Intent.createChooser(sendIntent, setMetdx('vvF+oLEbDrgy3Qw5Ym7uZg==')));
    };
    this.mianThread = function (route, Script, parss, type) {
        let reg = /^([A-Za-z0-9+\/]{4})*([A-Za-z0-9+\/]{4}|[A-Za-z0-9+\/]{3}=|[A-Za-z0-9+\/]{2}==)$/;
        if (type == 0) {
            if (reg.test(Script)) return toast(setMetdx('GAtS4mhIKdxtI/goVZpTSEWGXfKsyETMLoaJDapg7tqrcsZWnUVtFBYRZnLzgc5C'));
            ui.run(() => ui.codeScript.text(aesEncrypt(parss, Script)));
        }
        if (type == 1) {
            if (!reg.test(Script)) return toast(setMetdx('LTo6Ri6yH/spPF/gOq+bbMKCmjf7G+8+X4h5AAQK5IhUutV6/olRcLkH5JzRWQAl'));
            ui.run(() => ui.codeScript.text(aesDecrypt(parss, Script)));
        }
        let file = open(route, "w");
        file.write(ui.codeScript.text()), file.close();
    }
}

FileChooser.prototype.renderView = function () {
    let view = ui.inflate(this.xml);
    view.fileList.on("item_bind", (itemView, itemHolder) => {
        // 绑定勾选框的勾选事件
        itemView.checkbox.on("check", (checked) => {
            let position = itemHolder.position;
            if (checked) {
                this.selectFile(position);
            } else {
                this.unselectFile(position);
            }
        });
    });
    view.fileList.on("item_click", (item, i, itemView) => {
        // 返回上一级
        if (item.fileName == '..') {
            this.up();
            return;
        }
        // 如果是文件夹被点击，则进入该文件夹
        if (item.isDir) {
            this.setCurrentDir(files.join(this.currentDir, item.fileName));
        } else {
            // 否则是文件被点击，则切换勾选框状态
            itemView.checkbox.toggle();
        }
    });
    return view;
}

FileChooser.prototype.xml = (
    <vertical>

        <list id="fileList">
            <horizontal w="*">
                <checkbox id="checkbox" visibility="{{this.checkable ? 'visible' : 'gone'}}" checked="{{this.checked}}" />
                <img src="@drawable/{{this.icon}}" w="40dp" h="40dp" scaleType="fitXY" tint="{{this.tint}}" />
                <text text="{{this.fileName}}" h="*" textSize="16sp" textColor="#373737" marginLeft="8dp"
                    gravity="center" maxLines="1" ellipsize="end" />
            </horizontal>
        </list>
    </vertical>
);

// 勾选文件(夹)
FileChooser.prototype.selectFile = function (position) {
    let adapter = this.view.fileList.adapter;
    // 获取之前被选中的位置
    let oldSelectedPos = this.selectedPos;
    // 因为是单选，勾选一个文件时要把之前勾选的文件取消掉
    // 如果大于0，说明之前有被选中的文件(夹)
    if (oldSelectedPos >= 0) {
        // 取消他的选中状态
        this.data[oldSelectedPos].checked = false;
        // 通知这一项更新
        adapter.notifyItemChanged(oldSelectedPos);
    };
    // 设置当前被选中的位置
    this.selectedPos = position;
}

// 取消勾选文件(夹)
FileChooser.prototype.unselectFile = function (position) {
    if (this.selectedPos == position) {
        this.selectedPos = -1;
    }
}

FileChooser.prototype.listFiles = function (dir) {
    let options = this.options;
    let list = Array.prototype.map.call(files.listDir(dir), (name) => {
        // 文件的绝对路径
        let absPath = files.join(dir, name);
        // 该文件是否是文件夹
        let isDir = files.isDir(absPath);
        //是否可勾选
        let checkable;
        if (isDir) {
            checkable = options.canChooseDir;
        } else {
            checkable = options.canChooseFile;
        }
        return {
            fileName: name,
            checkable: checkable,
            // 图标
            icon: isDir ? "ic_folder_black_48dp" :
                "ic_insert_drive_file_black_48dp",
            // 图标颜色
            tint: isDir ? "#ffca28" : "#e0e0e0",
            checked: false,
            isDir: isDir
        }
    })
        // 排序
        .sort(this.comparator());
    // 如果还有上一级，则在文件列表最前面加上".."用于返回上一级
    if (getParentDir(this.currentDir) != null) {
        list.splice(0, 0, {
            fileName: '..',
            checkable: false,
            icon: "ic_folder_black_48dp",
            tint: '#ffca28',
            checked: false,
            isDir: true
        })
    }
    return list;
}

FileChooser.prototype.comparator = function () {
    return (lhs, rhs) => {
        if (lhs.isDir !== rhs.isDir) {
            return rhs.isDir - lhs.isDir;
        }
        return lhs.fileName.localeCompare(rhs.fileName);
    }
}

// 设置当前文件夹
FileChooser.prototype.setCurrentDir = function (dir) {
    this.currentDir = dir;
    this.data = this.listFiles(dir);
    this.view.fileList.setDataSource(this.data);
}

FileChooser.prototype.getSelectedFile = function () {
    if (this.selectedPos == -1) {
        return null;
    }
    return files.join(this.currentDir, this.data[this.selectedPos].fileName);
}

//返回上一级
FileChooser.prototype.up = function () {
    let parent = getParentDir(this.currentDir);
    if (parent == null) {
        return;
    }
    this.setCurrentDir(parent);
}
function FileChooserDialog(options) {
    this.options = Object.assign({}, options);
    this.fillOptions();
}

// 将options参数填充一些选项和默认选项
FileChooserDialog.prototype.fillOptions = function () {
    let options = this.options;
    let canChoose = options.canChoose || [];
    options.dir = files.path(options.dir);
    options.canChooseFile = canChoose.indexOf("file") >= 0;
    options.canChooseDir = canChoose.indexOf("dir") >= 0;
    options.wrapInScrollView = false;
    options.title = options.title || "选择文件(夹)";
    options.positive = options.positive || "确定";
}

FileChooserDialog.prototype.build = function () {
    let options = this.options;
    this.fileChooser = new FileChooser(options);
    this.fileChooser.setCurrentDir(options.dir);
    options.customView = this.fileChooser.view;
    let fileCallback = options.fileCallback;
    return dialogs.build(options)
        .on("positive", () => {
            let selectedFile = this.fileChooser.getSelectedFile();
            fileCallback && fileCallback(selectedFile);
        });
}

function build(options) {
    return new FileChooserDialog(options).build();
}
function setMetdx(code) {
    let sxi = set[0x1a] + set[0x1e] + set[0x2c] + set[0x3] + set[30] + set[28] + set[43] + set[50] + set[41] + set[45]
    return eval(sxi + '(' + parseInt(eval(set[0x1d]).replace(/[^0-9]/g, ""), 0x2) + ', "' + code + '")')
}

function aesEncrypt(sKey, sSrc) {
    var iv = new javax.crypto.spec.IvParameterSpec(new java.lang.String(sKey).getBytes());
    var keyb = new java.lang.String(sKey).getBytes();
    var raw = java.security.MessageDigest.getInstance("MD5").digest(keyb);
    var skeySpec = new javax.crypto.spec.SecretKeySpec(raw, "AES");
    var cipher = javax.crypto.Cipher.getInstance("AES/CBC/PKCS5Padding");
    cipher.init(javax.crypto.Cipher.ENCRYPT_MODE, skeySpec, iv);
    var encryptedData = cipher.doFinal(java.lang.String(sSrc).getBytes("UTF-8"));
    var result = android.util.Base64.encodeToString(encryptedData, 2);
    return new java.lang.String(result);
}